use cri_api::v1::{ContainerMetadata, Device, ImageSpec, KeyValue, LinuxContainerConfig, Mount, WindowsContainerConfig, ContainerConfig, PodSandboxMetadata, DnsConfig, PortMapping, LinuxPodSandboxConfig, WindowsPodSandboxConfig, PodSandboxConfig, LinuxContainerResources, LinuxContainerSecurityContext, HugepageLimit, Capability, NamespaceOption, SeLinuxOption, Int64Value, SecurityProfile, LinuxSandboxSecurityContext};
use serde::{Deserialize, Serialize};


/// A Containerd spec partial is used to create a Container
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct ContainerConfigPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub metadata: Option<ContainerMetadataPartial>,
    pub image: ImageSpecPartial,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub command: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub args: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub working_dir: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub envs: Option<Vec<KeyValue>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub mounts: Option<Vec<MountPartial>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub devices: Option<Vec<DevicePartial>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub labels: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub annotations: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub log_path: Option<String>,

    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub stdin: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub stdin_once: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub tty: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]

    pub linux: Option<LinuxContainerConfigPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub windows: Option<WindowsContainerConfig>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct ImageSpecPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub image: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub annotations: Option<std::collections::HashMap<String,String>>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct ContainerMetadataPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub name: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub attempt: Option<u32>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct MountPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub container_path: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub host_path: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub readonly: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub selinux_relabel: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub propagation: Option<i32>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct DevicePartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub container_path: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub host_path: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub permissions: Option<String>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct LinuxContainerConfigPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub resources: Option<LinuxContainerResourcesPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub security_context: Option<LinuxContainerSecurityContextPartial>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct LinuxContainerResourcesPartial {
    pub cpu: String,
    pub memory: String,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub cpu_shares: Option<i64>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub oom_score_adj: Option<i64>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub cpuset_cpus: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub cpuset_mems: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub hugepage_limits: Option<Vec<HugepageLimit>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub unified: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub memory_swap_limit_in_bytes: Option<i64>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct LinuxContainerSecurityContextPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub capabilities: Option<Capability>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub privileged: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub namespace_options: Option<NamespaceOption>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub selinux_options: Option<SeLinuxOption>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub run_as_user: Option<Int64Value>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub run_as_group: Option<Int64Value>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub run_as_username: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub readonly_rootfs: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub supplemental_groups: Option<Vec<i64>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub no_new_privs: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub masked_paths: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub readonly_paths: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub seccomp: Option<SecurityProfile>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub apparmor: Option<SecurityProfile>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub apparmor_profile: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub seccomp_profile_path: Option<String>,
}


//------------------------------------------------------------------------------------
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct PodSandboxConfigPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub metadata: Option<PodSandboxMetadataPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub hostname: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub log_directory: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub dns_config: Option<DnsConfigPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub port_mappings: Option<Vec<PortMappingPartial>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub labels: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub annotations: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub linux: Option<LinuxPodSandboxConfigPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub windows: Option<WindowsPodSandboxConfig>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct PodSandboxMetadataPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub name: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub uid: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub namespace: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub attempt: Option<u32>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct DnsConfigPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub servers: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub searches: Option<Vec<String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub options: Option<Vec<String>>,
}



#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct PortMappingPartial {
    pub container_port: i32,
    pub host_port: i32,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub protocol: Option<i32>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub host_ip: Option<String>,
}


#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct LinuxPodSandboxConfigPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub cgroup_parent: Option<String>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub security_context: Option<LinuxSandboxSecurityContextPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub sysctls: Option<std::collections::HashMap<String, String>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub overhead: Option<LinuxContainerResourcesPartial>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub resources: Option<LinuxContainerResourcesPartial>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct LinuxSandboxSecurityContextPartial {
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub namespace_options: Option<NamespaceOption>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub selinux_options: Option<SeLinuxOption>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub run_as_user: Option<Int64Value>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub run_as_group: Option<Int64Value>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub readonly_rootfs: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub supplemental_groups:  Option<Vec<i64>>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub privileged: Option<bool>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub seccomp: Option<SecurityProfile>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub apparmor: Option<SecurityProfile>,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub seccomp_profile_path: Option<String>,
}

#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct CriConfigPartial {
    pub container_config_Partial: ContainerConfigPartial,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    #[cfg_attr(feature = "utoipa", schema(value_type = HashMap<String, Any>))]
    pub pod_sandbox_config_Partial: Option<PodSandboxConfigPartial>,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(deny_unknown_fields, rename_all = "PascalCase")
)]
pub struct CriConfig {
    pub container_config: ContainerConfig,
    #[cfg_attr(
        feature = "serde",
        serde(skip_serializing_if = "Option::is_none")
    )]
    pub pod_sandbox_config: Option<PodSandboxConfig>,
}

impl From<ImageSpec> for ImageSpecPartial {
    fn from(spec: ImageSpec) -> Self {
        ImageSpecPartial {
            image: Some(spec.image),
            annotations: Some(spec.annotations),
        }
    }
}

impl From<ImageSpecPartial> for ImageSpec {
    fn from(partial: ImageSpecPartial) -> Self {
        ImageSpec {
            image: partial.image.unwrap_or_else(|| String::new()), // 默认值
            annotations: partial.annotations.unwrap_or_else(std::collections::HashMap::new), // 默认值
        }
    }
}

impl From<ContainerMetadata> for ContainerMetadataPartial {
    fn from(metadata: ContainerMetadata) -> Self {
        ContainerMetadataPartial {
            name: Some(metadata.name),
            attempt: Some(metadata.attempt),
        }
    }
}

impl From<ContainerMetadataPartial> for ContainerMetadata {
    fn from(partial: ContainerMetadataPartial) -> Self {
        ContainerMetadata {
            name: partial.name.unwrap_or_else(|| String::new()), // 默认值
            attempt: partial.attempt.unwrap_or(5), // 默认值
        }
    }
}

// 从 MountPartial 转换为 Mount
impl From<MountPartial> for Mount {
    fn from(partial: MountPartial) -> Self {
        Mount {
            container_path: partial.container_path.unwrap_or_default(),
            host_path: partial.host_path.unwrap_or_default(),
            readonly: partial.readonly.unwrap_or(false),
            selinux_relabel: partial.selinux_relabel.unwrap_or(false),
            // 0: 表示没有特殊的传播模式，通常是最安全的选择
            // 1: 表示挂载的更改在主机和容器之间是双向的。这意味着，如果你在容器内修改了挂载的内容，这些更改会反映到主机上，反之亦然
            // 2: 表示只允许主机的更改传播到容器，但容器内的更改不会反映到主机。
            // 3: 表示只允许容器内的更改传播到主机，而主机的更改不会影响到容器。
            propagation: partial.propagation.unwrap_or(0),
        }
    }
}

// 从 Mount 转换为 MountPartial
impl From<Mount> for MountPartial {
    fn from(mount: Mount) -> Self {
        MountPartial {
            container_path: Some(mount.container_path),
            host_path: Some(mount.host_path),
            readonly: Some(mount.readonly),
            selinux_relabel: Some(mount.selinux_relabel),
            propagation: Some(mount.propagation),
        }
    }
}

// 从 DevicePartial 转换为 Device
impl From<DevicePartial> for Device {
    fn from(partial: DevicePartial) -> Self {
        Device {
            container_path: partial.container_path.unwrap_or_default(),
            host_path: partial.host_path.unwrap_or_default(),
            permissions: partial.permissions.unwrap_or_else(|| "rwm".to_string()),
        }
    }
}

// 从 Device 转换为 DevicePartial
impl From<Device> for DevicePartial {
    fn from(device: Device) -> Self {
        DevicePartial {
            container_path: Some(device.container_path),
            host_path: Some(device.host_path),
            permissions: Some(device.permissions),
        }
    }
}

// 从 LinuxContainerResourcesPartial 转换为 LinuxContainerResources
impl From<LinuxContainerResourcesPartial> for LinuxContainerResources {
    fn from(partial: LinuxContainerResourcesPartial) -> Self {
        let (cpu_period, cpu_quota) = LinuxContainerResourcesPartial::parse_cpu(&partial.cpu);
        let memory_limit_in_bytes = LinuxContainerResourcesPartial::parse_memory(&partial.memory);
        LinuxContainerResources {
            cpu_period: cpu_period,
            cpu_quota:cpu_quota,
            cpu_shares: partial.cpu_shares.unwrap_or(0),
            memory_limit_in_bytes: memory_limit_in_bytes,
            oom_score_adj: partial.oom_score_adj.unwrap_or(0),
            cpuset_cpus: partial.cpuset_cpus.unwrap_or_default(),
            cpuset_mems: partial.cpuset_mems.unwrap_or_default(),
            hugepage_limits: partial.hugepage_limits.unwrap_or_default(),
            unified: partial.unified.unwrap_or_default(),
            memory_swap_limit_in_bytes: partial.memory_swap_limit_in_bytes.unwrap_or(0),
        }
    }
}

// 从 LinuxContainerResources 转换为 LinuxContainerResourcesPartial
impl From<LinuxContainerResources> for LinuxContainerResourcesPartial {
    fn from(resources: LinuxContainerResources) -> Self {
       let cpu = LinuxContainerResourcesPartial::format_cpu(resources.cpu_period,resources.cpu_quota);
        let memory =LinuxContainerResourcesPartial::format_memory(resources.memory_limit_in_bytes);
        LinuxContainerResourcesPartial {
            cpu,
            memory,
            cpu_shares: Some(resources.cpu_shares),
            oom_score_adj: Some(resources.oom_score_adj),
            cpuset_cpus: Some(resources.cpuset_cpus),
            cpuset_mems: Some(resources.cpuset_mems),
            hugepage_limits: Some(resources.hugepage_limits),
            unified: Some(resources.unified),
            memory_swap_limit_in_bytes: Some(resources.memory_swap_limit_in_bytes),
        }
    }
}

// 从 LinuxContainerSecurityContextPartial 转换为 LinuxContainerSecurityContext
impl From<LinuxContainerSecurityContextPartial> for LinuxContainerSecurityContext {
    fn from(partial: LinuxContainerSecurityContextPartial) -> Self {
        LinuxContainerSecurityContext {
            capabilities: partial.capabilities, // 直接使用 Option
            privileged: partial.privileged.unwrap_or(false), // 默认值为 false
            namespace_options: partial.namespace_options, // 直接使用 Option
            selinux_options: partial.selinux_options, // 直接使用 Option
            run_as_user: partial.run_as_user, // 直接使用 Option
            run_as_group: partial.run_as_group, // 直接使用 Option
            run_as_username: partial.run_as_username.unwrap_or_default(), // 默认值为空字符串
            readonly_rootfs: partial.readonly_rootfs.unwrap_or(false), // 默认值为 false
            supplemental_groups: partial.supplemental_groups.unwrap_or_default(), // 默认值为 []
            no_new_privs: partial.no_new_privs.unwrap_or(false), // 默认值为 false
            masked_paths: partial.masked_paths.unwrap_or_default(), // 默认值为 []
            readonly_paths: partial.readonly_paths.unwrap_or_default(), // 默认值为 []
            seccomp: partial.seccomp, // 直接使用 Option
            apparmor: partial.apparmor, // 直接使用 Option
            apparmor_profile: partial.apparmor_profile.unwrap_or_default(), // 默认值为空字符串
            seccomp_profile_path: partial.seccomp_profile_path.unwrap_or_default(), // 默认值为空字符串
        }
    }
}

// 从 LinuxContainerSecurityContext 转换为 LinuxContainerSecurityContextPartial
impl From<LinuxContainerSecurityContext> for LinuxContainerSecurityContextPartial {
    fn from(context: LinuxContainerSecurityContext) -> Self {
        LinuxContainerSecurityContextPartial {
            capabilities: context.capabilities, // 直接使用 Option
            privileged: Some(context.privileged), // 直接使用 Some
            namespace_options: context.namespace_options, // 直接使用 Option
            selinux_options: context.selinux_options, // 直接使用 Option
            run_as_user: context.run_as_user, // 直接使用 Option
            run_as_group: context.run_as_group, // 直接使用 Option
            run_as_username: Some(context.run_as_username), // 直接使用 Some
            readonly_rootfs: Some(context.readonly_rootfs), // 直接使用 Some
            supplemental_groups: Some(context.supplemental_groups), // 直接使用 Some
            no_new_privs: Some(context.no_new_privs), // 直接使用 Some
            masked_paths: Some(context.masked_paths), // 直接使用 Some
            readonly_paths: Some(context.readonly_paths), // 直接使用 Some
            seccomp: context.seccomp, // 直接使用 Option
            apparmor: context.apparmor, // 直接使用 Option
            apparmor_profile: Some(context.apparmor_profile), // 直接使用 Some
            seccomp_profile_path: Some(context.seccomp_profile_path), // 直接使用 Some
        }
    }
}

// 从 LinuxContainerConfigPartial 转换为 LinuxContainerConfig
impl From<LinuxContainerConfigPartial> for LinuxContainerConfig {
    fn from(partial: LinuxContainerConfigPartial) -> Self {
        LinuxContainerConfig {
            resources: partial.resources.map(Into::into),
            security_context: partial.security_context.map(Into::into),
        }
    }
}

// 从 LinuxContainerConfig 转换为 LinuxContainerConfigPartial
impl From<LinuxContainerConfig> for LinuxContainerConfigPartial {
    fn from(config: LinuxContainerConfig) -> Self {
        LinuxContainerConfigPartial {
            resources: config.resources.map(Into::into),
            security_context: config.security_context.map(Into::into),
        }
    }
}


// 从 PodSandboxMetadataPartial 转换为 PodSandboxMetadata
impl From<PodSandboxMetadataPartial> for PodSandboxMetadata {
    fn from(partial: PodSandboxMetadataPartial) -> Self {
        PodSandboxMetadata {
            name: partial.name.unwrap_or_default(),         // 默认值为空字符串
            uid: partial.uid.unwrap_or_default(),           // 默认值为空字符串
            namespace: partial.namespace.unwrap_or_default(), // 默认值为空字符串
            attempt: partial.attempt.unwrap_or(0),          // 默认值为0
        }
    }
}

// 从 PodSandboxMetadata 转换为 PodSandboxMetadataPartial
impl From<PodSandboxMetadata> for PodSandboxMetadataPartial {
    fn from(metadata: PodSandboxMetadata) -> Self {
        PodSandboxMetadataPartial {
            name: Some(metadata.name),                      // 直接使用 Some
            uid: Some(metadata.uid),                        // 直接使用 Some
            namespace: Some(metadata.namespace),            // 直接使用 Some
            attempt: Some(metadata.attempt),                // 直接使用 Some
        }
    }
}


// 从 LinuxSandboxSecurityContextPartial 转换为 LinuxSandboxSecurityContext
impl From<LinuxSandboxSecurityContextPartial> for LinuxSandboxSecurityContext {
    fn from(partial: LinuxSandboxSecurityContextPartial) -> Self {
        LinuxSandboxSecurityContext {
            namespace_options: partial.namespace_options, // 直接使用 Option
            selinux_options: partial.selinux_options, // 直接使用 Option
            run_as_user: partial.run_as_user, // 直接使用 Option
            run_as_group: partial.run_as_group, // 直接使用 Option
            readonly_rootfs: partial.readonly_rootfs.unwrap_or(false), // 默认值为 false
            supplemental_groups: partial.supplemental_groups.unwrap_or_default(), // 默认值为 []
            privileged: partial.privileged.unwrap_or(false), // 默认值为 false
            seccomp: partial.seccomp, // 直接使用 Option
            apparmor: partial.apparmor, // 直接使用 Option
            seccomp_profile_path: partial.seccomp_profile_path.unwrap_or_default(), // 默认值为空字符串
        }
    }
}

// 从 LinuxSandboxSecurityContext 转换为 LinuxSandboxSecurityContextPartial
impl From<LinuxSandboxSecurityContext> for LinuxSandboxSecurityContextPartial {
    fn from(context: LinuxSandboxSecurityContext) -> Self {
        LinuxSandboxSecurityContextPartial {
            namespace_options: context.namespace_options, // 直接使用 Option
            selinux_options: context.selinux_options, // 直接使用 Option
            run_as_user: context.run_as_user, // 直接使用 Option
            run_as_group: context.run_as_group, // 直接使用 Option
            readonly_rootfs: Some(context.readonly_rootfs), // 直接使用 Some
            supplemental_groups: Some(context.supplemental_groups), // 直接使用 Some
            privileged: Some(context.privileged), // 直接使用 Some
            seccomp: context.seccomp, // 直接使用 Option
            apparmor: context.apparmor, // 直接使用 Option
            seccomp_profile_path: Some(context.seccomp_profile_path), // 直接使用 Some
        }
    }
}

// 从 LinuxPodSandboxConfigPartial 转换为 LinuxPodSandboxConfig
impl From<LinuxPodSandboxConfigPartial> for LinuxPodSandboxConfig {
    fn from(partial: LinuxPodSandboxConfigPartial) -> Self {
        LinuxPodSandboxConfig {
            cgroup_parent: partial.cgroup_parent.unwrap_or_default(), // 默认值为空字符串
            security_context: partial.security_context.map(Into::into), // 使用 Option::map 进行转换
            sysctls: partial.sysctls.unwrap_or_default(), // 默认值为空 HashMap
            overhead: partial.overhead.map(Into::into), // 使用 Option::map 进行转换
            resources: partial.resources.map(Into::into), // 使用 Option::map 进行转换
        }
    }
}

// 从 LinuxPodSandboxConfig 转换为 LinuxPodSandboxConfigPartial
impl From<LinuxPodSandboxConfig> for LinuxPodSandboxConfigPartial {
    fn from(config: LinuxPodSandboxConfig) -> Self {
        LinuxPodSandboxConfigPartial {
            cgroup_parent: Some(config.cgroup_parent), // 直接使用 Some
            security_context: config.security_context.map(Into::into), // 使用 Option::map 进行转换
            sysctls: Some(config.sysctls), // 直接使用 Some
            overhead: config.overhead.map(Into::into), // 使用 Option::map 进行转换
            resources: config.resources.map(Into::into), // 使用 Option::map 进行转换
        }
    }
}





// 从 DnsConfigPartial 转换为 DnsConfig
impl From<DnsConfigPartial> for DnsConfig {
    fn from(partial: DnsConfigPartial) -> Self {
        DnsConfig {
            servers: partial.servers.unwrap_or_default(),
            searches: partial.searches.unwrap_or_default(),
            options: partial.options.unwrap_or_default(),
        }
    }
}

// 从 DnsConfig 转换为 DnsConfigPartial
impl From<DnsConfig> for DnsConfigPartial {
    fn from(config: DnsConfig) -> Self {
        DnsConfigPartial {
            servers: Some(config.servers),
            searches: Some(config.searches),
            options: Some(config.options),
        }
    }
}


// 从 PortMappingPartial 转换为 PortMapping
impl From<PortMappingPartial> for PortMapping {
    fn from(partial: PortMappingPartial) -> Self {
        PortMapping {
            protocol: partial.protocol.unwrap_or(0), // 默认值
            container_port: partial.container_port,
            host_port: partial.host_port,
            host_ip: partial.host_ip.unwrap_or_default(),
        }
    }
}

// 从 PortMapping 转换为 PortMappingPartial
impl From<PortMapping> for PortMappingPartial {
    fn from(mapping: PortMapping) -> Self {
        PortMappingPartial {
            protocol: Some(mapping.protocol),
            container_port: mapping.container_port,
            host_port: mapping.host_port,
            host_ip: Some(mapping.host_ip),
        }
    }
}



impl LinuxContainerResourcesPartial{

    /// 解析内存参数，支持 Ki、Mi、Gi、K、M、G 等单位
    /// 例如: "512Mi", "1Gi", "1024Ki"
    pub fn parse_memory(memory: &str) -> i64 {
        if memory.is_empty() {
            return 0;
        }
        let mut value_str = memory;
        let mut multiplier = 1;

        if memory.ends_with("Ki") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1024;
        } else if memory.ends_with("Mi") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1024 * 1024;
        } else if memory.ends_with("Gi") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1024 * 1024 * 1024;
        }else if memory.ends_with("Kb") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1000;
        } else if memory.ends_with("Mb") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1000 * 1000;
        } else if memory.ends_with("Gb") {
            value_str = &memory[..memory.len() - 2];
            multiplier = 1000 * 1000 * 1000;
        } else if memory.ends_with('K') {
            value_str = &memory[..memory.len() - 1];
            multiplier = 1000;
        } else if memory.ends_with('M') {
            value_str = &memory[..memory.len() - 1];
            multiplier = 1000 * 1000;
        } else if memory.ends_with('G') {
            value_str = &memory[..memory.len() - 1];
            multiplier = 1000 * 1000 * 1000;
        }

        match value_str.parse::<i64>() {
            Ok(value) => value * multiplier,
            Err(_) => 0,
        }
    }

    /// 解析 CPU 参数，支持 cores 和 millicores
    /// 例如: "0.5", "500m", "2"
    pub fn parse_cpu(cpu: &str) -> (i64, i64) {
        if cpu.is_empty() {
            return (0, 0);
        }
        // 默认周期为 100ms (100000us)
        const PERIOD: i64 = 100000;
        let mut quota = 0;

        if cpu.ends_with('m') {
            // millicores 格式 (例如 "500m")
            if let Ok(millicores) = cpu[..cpu.len() - 1].parse::<i64>() {
                quota = PERIOD * millicores / 1000;
            }
        } else {
            // 完整核心数格式 (例如 "0.5" 或 "2")
            if let Ok(cores) = cpu.parse::<f64>() {
                quota = (cores * PERIOD as f64) as i64;
            }
        }

        (PERIOD, quota)
    }

    /// 将字节数转换为可读的内存表示
    /// 例如: 512MiB, 1GiB 等
    pub fn format_memory(bytes: i64) -> String {
        if bytes == 0 {
            return "0".to_string();
        }

        // 二进制单位 (1024)
        let gib = 1024 * 1024 * 1024;
        let mib = 1024 * 1024;
        let kib = 1024;

        if bytes % gib == 0 {
            format!("{}Gi", bytes / gib)
        } else if bytes % mib == 0 {
            format!("{}Mi", bytes / mib)
        } else if bytes % kib == 0 {
            format!("{}Ki", bytes / kib)
        } else {
            bytes.to_string()
        }
    }

    /// 将 CPU 配额转换为可读的 CPU 表示
    /// period 和 quota 转换为 cores 或 millicores
    pub fn format_cpu(period: i64, quota: i64) -> String {
        if period == 0 || quota == 0 {
            return "0".to_string();
        }

        let cores = quota as f64 / period as f64;

        // 如果是整数个核心，直接返回数字
        if (cores * 1000.0).round() % 1000.0 == 0.0 {
            return format!("{}", cores as i64);
        }

        // 否则转换为 millicores
        let millicores = (cores * 1000.0).round() as i64;
        format!("{}m", millicores)
    }

}


impl ContainerConfigPartial {
    pub fn to_container_config(self) -> ContainerConfig {
        ContainerConfig {
            metadata: self.metadata.as_ref().cloned().map(From::from),
            image:   Some(self.image.clone().into()),
            command: self.command.unwrap_or_default(),
            args: self.args.unwrap_or_default(),
            working_dir: self.working_dir.unwrap_or_default(),
            envs: self.envs.unwrap_or_default(),
            mounts:  self.mounts.unwrap_or_default().iter().cloned().map(From::from).collect(),
            devices: self.devices.unwrap_or_default().iter().cloned().map(From::from).collect(),
            labels: self.labels.unwrap_or_default(),
            annotations: self.annotations.unwrap_or_default(),
            log_path: self.log_path.unwrap_or_default(),
            stdin: self.stdin.unwrap_or(false),
            stdin_once: self.stdin_once.unwrap_or(false),
            tty: self.tty.unwrap_or(false),
            linux: self.linux.as_ref().cloned().map(From::from),
            windows: self.windows,
        }
    }
    pub fn from_container_config(config: ContainerConfig) -> Self {
        Self {
            metadata: config.metadata.as_ref().cloned().map(From::from),
            image: config.image.as_ref().cloned().map(From::from).unwrap(),
            command: if config.command.is_empty() {
                None
            } else {
                Some(config.command)
            },
            args: if config.args.is_empty() {
                None
            } else {
                Some(config.args)
            },
            working_dir: if config.working_dir.is_empty() {
                None
            } else {
                Some(config.working_dir)
            },
            envs: if config.envs.is_empty() {
                None
            } else {
                Some(config.envs)
            },
            mounts: if config.mounts.is_empty() {
                None
            } else {
                Some(config.mounts.iter().cloned().map(From::from).collect())
            },
            devices: if config.devices.is_empty() {
                None
            } else {
                Some(config.devices.iter().cloned().map(From::from).collect())
            },
            labels: if config.labels.is_empty() {
                None
            } else {
                Some(config.labels)
            },
            annotations: if config.annotations.is_empty() {
                None
            } else {
                Some(config.annotations)
            },
            log_path: if config.log_path.is_empty() {
                None
            } else {
                Some(config.log_path)
            },
            stdin: if config.stdin { Some(true) } else { None },
            stdin_once: if config.stdin_once { Some(true) } else { None },
            tty: if config.tty { Some(true) } else { None },
            linux: config.linux.as_ref().cloned().map(From::from),
            windows: config.windows,
        }
    }
}

impl PodSandboxConfigPartial {
    pub fn to_pod_sandbox_config(self) -> PodSandboxConfig {
        PodSandboxConfig {
            metadata: self.metadata.as_ref().cloned().map(From::from),
            hostname: self.hostname.unwrap_or_default(),
            log_directory: self.log_directory.unwrap_or_default(),
            dns_config: self.dns_config.as_ref().cloned().map(From::from),
            port_mappings: self.port_mappings
                .as_ref()
                .map(|mappings| mappings.iter().cloned().map(From::from).collect())
                .unwrap_or_default(),
            labels: self.labels.unwrap_or_default(),
            annotations: self.annotations.unwrap_or_default(),
            linux: self.linux.as_ref().cloned().map(From::from),
            windows: self.windows,
        }
    }

    pub fn from_pod_sandbox_config(config: PodSandboxConfig) -> Self {
        Self {
            metadata: config.metadata.as_ref().cloned().map(From::from),
            hostname: if config.hostname.is_empty() {
                None
            } else {
                Some(config.hostname)
            },
            log_directory: if config.log_directory.is_empty() {
                None
            } else {
                Some(config.log_directory)
            },
            dns_config: config.dns_config.as_ref().cloned().map(From::from),
            port_mappings: if config.port_mappings.is_empty() {
                None
            } else {
                Some(config.port_mappings.iter().cloned().map(From::from).collect())
            },
            labels: if config.labels.is_empty() {
                None
            } else {
                Some(config.labels)
            },
            annotations: if config.annotations.is_empty() {
                None
            } else {
                Some(config.annotations)
            },
            linux: config.linux.as_ref().cloned().map(From::from),
            windows: config.windows,
        }
    }
}

impl CriConfigPartial {
    pub fn to_cri_config(self) -> CriConfig {
        CriConfig {
            container_config: self.container_config_Partial.to_container_config(),
            pod_sandbox_config: self.pod_sandbox_config_Partial.map(|p| p.to_pod_sandbox_config()),
        }
    }

    pub fn from_cri_config(config: CriConfig) -> Self {
        Self {
            container_config_Partial: ContainerConfigPartial::from_container_config(config.container_config),
            pod_sandbox_config_Partial: config.pod_sandbox_config.map(|p| PodSandboxConfigPartial::from_pod_sandbox_config(p)),
        }
    }
}

impl CriConfig {
    pub fn from_partial(partial: CriConfigPartial) -> Self {
        partial.to_cri_config()
    }
}



